package com.jkt.rms.dataservice;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;

import org.hibernate.ReplicationMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import com.jkt.rms.commons.utils.RMSDataServiceException;
import com.jkt.rms.commons.utils.RMSException;

public abstract class AbstractDataService<BO> extends HibernateDaoSupport {

	protected abstract Class<BO> getReferenceClass();

	protected Order getDefaultOrder() {
		return null;
	}

	protected void checkNotNull(Object o) {
		if (o == null)
			throw new NullPointerException();
	}

	@SuppressWarnings("unchecked")
	public BO save(BO obj) {
		Serializable id = getHibernateTemplate().save(obj);
		getHibernateTemplate().flush();
		return (BO) (getHibernateTemplate().load(getReferenceClass(), id));
	}

	@Deprecated
	@SuppressWarnings("unchecked")
	public BO update(BO obj) {
		checkNotNull(obj);
		getHibernateTemplate().update(obj);
		getHibernateTemplate().flush();
		return (BO) (getHibernateTemplate().load(getReferenceClass(),
				(Serializable) obj));
	}
	
	public void updateObj(BO obj) {
		checkNotNull(obj);
		getHibernateTemplate().update(obj);
		getHibernateTemplate().flush();
	}

	public void delete(BO obj) {
		checkNotNull(obj);
		getHibernateTemplate().delete(obj);
		getHibernateTemplate().flush();
	}

	public void deleteAll(Collection<BO> data) {
		checkNotNull(data);
		getHibernateTemplate().deleteAll(data);
		getHibernateTemplate().flush();
	}

	@SuppressWarnings("unchecked")
	public BO find(Long id) {
		Object object = getHibernateTemplate().get(getReferenceClass(), id);
		return (BO) object;
	}

	@SuppressWarnings("unchecked")
	public BO find(Long id, @SuppressWarnings("rawtypes") Class clazz) {
		return (BO) getHibernateTemplate().get(clazz, id);
	}

	@SuppressWarnings("unchecked")
	public BO find(Integer id) {
		Object object = getHibernateTemplate().get(getReferenceClass(), id);
		return (BO) object;
	}

	@SuppressWarnings("unchecked")
	public BO find(Integer id, Class clazz) {
		return (BO) getHibernateTemplate().get(clazz, id);
	}

	@SuppressWarnings("unchecked")
	public BO find(String id) {
		Object object = getHibernateTemplate().get(getReferenceClass(), id);
		return (BO) object;
	}

	@SuppressWarnings("unchecked")
	public List<BO> findAll() {
		return (List<BO>) getHibernateTemplate().loadAll(getReferenceClass());
	}

	@SuppressWarnings("unchecked")
	public List<BO> findByCriteria(DetachedCriteria crit) {
		return (List<BO>) getHibernateTemplate().findByCriteria(crit);
	}

	@SuppressWarnings("unchecked")
	public List<BO> findByCriteria(DetachedCriteria crit, int offset,
			int maxResults) {
		return (List<BO>) getHibernateTemplate().findByCriteria(crit, offset,
				maxResults);
	}

	@SuppressWarnings("unchecked")
	public BO find(Serializable id) {
		return (BO) getHibernateTemplate().get(getReferenceClass(), id);
	}

	public void init() {

	}

	/*
	 * public void evict(BO bo) { getHibernateTemplate().evict(bo); }
	 */

	public void evict(Object object) {
		getHibernateTemplate().evict(object);
	}

	public void clear() {
		getHibernateTemplate().clear();
	}

	public void flush() {
		getHibernateTemplate().flush();
	}

	public void saveOrUpdateAll(Collection<BO> listBTM) {
		checkNotNull(listBTM);
		getHibernateTemplate().saveOrUpdateAll(listBTM);
		getHibernateTemplate().flush();
	}

	public void saveOrUpdate(BO obj) throws RMSException {
		checkNotNull(obj);
		try {

			getHibernateTemplate().saveOrUpdate(obj);
			getHibernateTemplate().flush();
		} catch (DataAccessException dae) {
			throw new RMSDataServiceException(dae);
		}
	}

	public void replicate(BO obj) {
		try {
			checkNotNull(obj);
			getHibernateTemplate().replicate(obj, ReplicationMode.OVERWRITE);
			getHibernateTemplate().flush();
		} catch (DataAccessException dae) {
			throw new RMSDataServiceException(dae);
		}
	}

	public BO refresh(BO obj) {
		getHibernateTemplate().refresh(obj);
		return obj;
	}

	@SuppressWarnings("unchecked")
	protected List<BO> executeQuery(String strQuery) {
		checkNotNull(strQuery);
		return getHibernateTemplate().find(strQuery);
	}
}
